#include "SpiInitHelper.h"

#include "SimpleCompletion.h"

Spi_Transport_Def spi1_obj;

//SPIx Config
void App_SPIxCfg(void) {
  stc_spi_init_t stcSpiInit;
  stc_spi_delay_t stcSpiDelay;

  /* Enable SPI1 clock */
  FCG_Fcg1PeriphClockCmd(FCG1_PERIPH_SPI1, ENABLE);
  /************************* Configure SPI1***************************/
  SPI_StructInit(&stcSpiInit);
  stcSpiInit.u32WireMode = SPI_4_WIRE;
  stcSpiInit.u32TransMode = SPI_FULL_DUPLEX;
  stcSpiInit.u32MasterSlave = SPI_MASTER;
  stcSpiInit.u32Parity = SPI_PARITY_INVD;
  stcSpiInit.u32SpiMode = SPI_MD_0;
  stcSpiInit.u32BaudRatePrescaler = SPI_BR_CLK_DIV2;
  stcSpiInit.u32DataBits = SPI_DATA_SIZE_8BIT;
  stcSpiInit.u32FirstBit = SPI_FIRST_MSB;
  stcSpiInit.u32SuspendMode = SPI_COM_SUSP_FUNC_OFF;
  stcSpiInit.u32FrameLevel = SPI_1_FRAME;
  (void) SPI_Init(CM_SPI1, &stcSpiInit);

  SPI_DelayStructInit(&stcSpiDelay);
  stcSpiDelay.u32IntervalDelay = SPI_INTERVAL_TIME_2SCK;
  stcSpiDelay.u32ReleaseDelay = SPI_RELEASE_TIME_1SCK;
  stcSpiDelay.u32SetupDelay = SPI_SETUP_TIME_4SCK;
  (void) SPI_DelayTimeConfig(CM_SPI1, &stcSpiDelay);

//  /* SPI loopback function configuration */
//  SPI_LoopbackModeConfig(CM_SPI3, SPI_LOOPBACK_INVD);
//  /* SPI parity check error self diagnosis configuration */
//  SPI_ParityCheckCmd(CM_SPI3, DISABLE);
//  /* SPI valid SS signal configuration */
//  SPI_SSPinSelect(CM_SPI3, SPI_PIN_SS0);
//  /* SPI SS signal valid level configuration */
//  SPI_SSValidLevelConfig(CM_SPI3, SPI_PIN_SS0, DISABLE);
  /* Enable interrupt function*/
  SPI_IntCmd(CM_SPI1,  SPI_INT_ERR, ENABLE);
  /* Enable SPI1 */
  //SPI_Cmd(CM_SPI1, ENABLE);
}

//// spi3 接收中断
//void INT_SRC_DMA2_TC3_IrqCallback(void) {
//  DMA_ClearTransCompleteStatus(CM_DMA2, DMA_CH3);
//	DMA_ChCmd(CM_DMA2, DMA_CH2, DISABLE);
//  DMA_ChCmd(CM_DMA2, DMA_CH3, DISABLE);
//  completion_done(&(spi3_obj.spi_transport_sem));
//}// spi3 接收中断

//// spi3 空闲中断
//void INT_SRC_SPI3_SPII_IrqCallback(void) {
//	SPI_ClearStatus(CM_SPI3, SPI_FLAG_IDLE);
//	SPI_IntCmd(CM_SPI3,  SPI_INT_IDLE, DISABLE);
//	DMA_ClearTransCompleteStatus(CM_DMA2, DMA_CH3);
//	DMA_ChCmd(CM_DMA2, DMA_CH2, DISABLE);
//  DMA_ChCmd(CM_DMA2, DMA_CH3, DISABLE);
//  completion_done(&(spi3_obj.spi_transport_sem));
//} // spi3 空闲中断

// SPI管理对象初始化
rt_err_t Init_Spi1_Obj(Spi_Transport_Def* obj, char* name, CM_SPI_TypeDef *SPI_CMx, CM_DMA_TypeDef *CM_DMAx, uint8_t DMAx_CH) {
  rt_mutex_init(&(obj->spi_lock), "spi1 port mutex", RT_IPC_FLAG_PRIO);
  rt_sem_init(&(obj->spi_transport_sem), "spi1 transport sem", 0, RT_IPC_FLAG_PRIO);
	
	obj->spi_status = 0;
	obj->spi_translate_status = SPI_TRANSLATE_IDLE;
  STATU_SET(obj->spi_status, SPI_INITED);
	
	obj->cmd_size = 0;
	obj->send_size = 0;
	obj->recv_size = 0;
	
	obj->spi_cmd_cache_size = 16;// 命令字节
	rt_memset(obj->spi_cmd_buf, 0, obj->spi_cmd_cache_size);
	obj->spi_data_cache_size = 4096;// 数据字节
	rt_memset(obj->spi_data_buf, 0, obj->spi_data_cache_size);

	obj->cm_dma = CM_DMAx;
	obj->ch_dma = DMAx_CH;
	obj->spi_cm = SPI_CMx;
	
	switch ((uint32_t)(SPI_CMx)){
		case (uint32_t)CM_SPI1:
			obj->aos_send_src_event = EVT_SRC_SPI1_SPTI;
			break;
		case (uint32_t)CM_SPI2:
			obj->aos_send_src_event = EVT_SRC_SPI2_SPTI;
			break;
		case (uint32_t)CM_SPI3:
			obj->aos_send_src_event = EVT_SRC_SPI3_SPTI;
			break;
		case (uint32_t)CM_SPI4:
			obj->aos_send_src_event = EVT_SRC_SPI4_SPTI;
			break;
		case (uint32_t)CM_SPI5:
			obj->aos_send_src_event = EVT_SRC_SPI5_SPTI;
			break;
		case (uint32_t)CM_SPI6:
			obj->aos_send_src_event = EVT_SRC_SPI6_SPTI;
			break;
		default:
			for (;;) {;} // 出错
	}
	
	if ( CM_DMAx == CM_DMA1 ) {
		switch ( DMAx_CH ) {
			case DMA_CH0:
				obj->aos_tag = AOS_DMA1_0;
			  break;
			case DMA_CH1:
				obj->aos_tag = AOS_DMA1_1;
			  break;
			case DMA_CH2:
				obj->aos_tag = AOS_DMA1_2;
			  break;
			case DMA_CH3:
				obj->aos_tag = AOS_DMA1_3;
			  break;
			case DMA_CH4:
				obj->aos_tag = AOS_DMA1_4;
			  break;
			case DMA_CH5:
				obj->aos_tag = AOS_DMA1_5;
			  break;
			case DMA_CH6:
				obj->aos_tag = AOS_DMA1_6;
			  break;
			case DMA_CH7:
				obj->aos_tag = AOS_DMA1_7;
			  break;
			default:
				for (;;) {;} // 出错
		}
	} else if ( CM_DMAx == CM_DMA2 ) {
		switch ( DMAx_CH ) {
			case DMA_CH0:
				obj->aos_tag = AOS_DMA2_0;
			  break;
			case DMA_CH1:
				obj->aos_tag = AOS_DMA2_1;
			  break;
			case DMA_CH2:
				obj->aos_tag = AOS_DMA2_2;
			  break;
			case DMA_CH3:
				obj->aos_tag = AOS_DMA2_3;
			  break;
			case DMA_CH4:
				obj->aos_tag = AOS_DMA2_4;
			  break;
			case DMA_CH5:
				obj->aos_tag = AOS_DMA2_5;
			  break;
			case DMA_CH6:
				obj->aos_tag = AOS_DMA2_6;
			  break;
			case DMA_CH7:
				obj->aos_tag = AOS_DMA2_7;
			  break;
			default:
				for (;;) {;} // 出错
		}
	} else {
		for (;;) {;} // 出错
	}
	
	return RT_EOK;
}

rt_err_t Spi_Start_Wait_Interface(Spi_Transport_Def *obj) {
  /* Enable DMA channel */
	// 配置触发
	AOS_SetTriggerEventSrc(obj->aos_tag, obj->aos_send_src_event);
	obj->spi_translate_status = SPI_TRANSLATE_CMD;
	// 发送使能
	DMA_SetSrcAddr(obj->cm_dma, obj->ch_dma, (uint32_t) (obj->spi_cmd_buf));
  DMA_SetTransCount(obj->cm_dma, obj->ch_dma, obj->cmd_size);
	
	DMA_ChCmd(obj->cm_dma, obj->ch_dma, ENABLE);
	SPI_Cmd(obj->spi_cm, ENABLE);
	rt_err_t res = completion_wait(&(obj->spi_transport_sem), 500);
	return res;
}

rt_err_t Spi_Set_Band_Interface(Spi_Transport_Def *obj, uint32_t u32BaudRatePrescaler){
	LL_PERIPH_WE(LL_PERIPH_PWC_CLK_RMU);
	uint32_t reg = READ_REG32(obj->spi_cm->CFG2);
	STATU_SET(reg, u32BaudRatePrescaler);
	WRITE_REG32(obj->spi_cm->CFG2, reg);
	LL_PERIPH_WP(LL_PERIPH_PWC_CLK_RMU);
	return RT_EOK;
}
